package com.lpf.nio;

import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * 功能描述：关于scattering和gathering
 *          从客户端读取数据到三个buffer，然后写回到客户端
 *
 * 进入 telnet 直接输入字符串，不要按 'CTRL+]'
 * 回车也算一个字节
 *
 * @author lpf
 * @date 2019/11/26 10:43
 * @version: 1.0
 **/
public class NioTest11 {

    public static void main(String[] arg) throws Exception {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8899));

        int mesLength = 2 + 3 + 4;

        ByteBuffer b1 = ByteBuffer.allocate(2);
        ByteBuffer b2 = ByteBuffer.allocate(3);
        ByteBuffer b3 = ByteBuffer.allocate(4);

        ByteBuffer[] buffers = {b1, b2, b3};

        SocketChannel socketChannel = serverSocketChannel.accept();

        while (true) {
            int byteRead = 0;

            // 当这个循环结束之后，说明这三个buffer都已经堵满了
            // 多次回车试一下，看控制台打印
            while (byteRead < mesLength) {
                long r = socketChannel.read(buffers);
                byteRead += r;

                System.out.println("byteRead: " + byteRead);

                Arrays.stream(buffers)
                        // 最终打印的是拼装好的字符串
                        .map(buffer -> "position:" + buffer.position() + " limit:" + buffer.limit())
                        .forEach(System.out::println);
            }

            // 把每一个buffer进行读写切换
            Arrays.asList(buffers).forEach(Buffer::flip);

            // 将数据写回给客户端
            long byteWrite = 0;
            while (byteWrite < mesLength) {
                long r = socketChannel.write(buffers);
                byteWrite += r;
            }

            // 清空buffer
            Arrays.asList(buffers).forEach(Buffer::clear);

            System.out.println("byteRead: " + byteRead + ",byteWrite: " + byteWrite + ",mesLength: " + mesLength);
        }

    }
}
